package away3d.animators ;


import away3d.errors.AbstractMethodError ;
import away3d.events.AnimatorEvent ;
import away3d.library.assets.AssetType ;
import away3d.library.assets.IAsset ;
import away3d.library.assets.NamedAssetBase ;
import flash.display.Sprite ;
import flash.events.Event ;
import flash.events.EventDispatcher ;
import flash.utils.getTimer ;

/**
 * AnimationControllerBase provides an abstract base class for classes that control a subtype of AnimationStateBase.
 *
 * @see away3d.core.animation.AnimationStateBase
 *
 */
class AnimatorBase extends NamedAssetBase implements IAsset
{
    
    
    private var _broadcaster    : Sprite;
    private var _isPlaying      : Bool;
    private var _startEvent     : AnimatorEvent;
    private var _stopEvent      : AnimatorEvent;
    private var _time           : Int;
    private var _timeScale      : Float;
    
    
    
    public function new()
    {
        
        _timeScale      = 1 ;
        _broadcaster    = new Sprite();
        // start();
        
    }
    
    
    public function timeScale( get_timeScale, set_timeScale ) : Float
    
    /**
     * The amount by which passed time should be scaled. Used to slow down or speed up animations.
     */
    public function get_timeScale() : Float
    {
        
        return _timeScale ;
        
    }
    
    
    public function set_timeScale( value: Float ) : Float
    {
        
        _timeScale = value ;
        return _timeScale ;
        
    }
    
    
    public function getAssetType() : String
    {
        
        return AssetType.ANIMATOR;
        
    }
    
    public function stop()
    {
        
        notifyStop();
        
    }
    
    
    private function notifyStart()
    {
        
        if( _isPlaying )
        {
            
            return;
            
        }
        
        _isPlaying = true ;
        
        if( !hasEventListener( AnimatorEvent.START ) ) return ;
        
        if( !_startEvent ) _startEvent = new AnimatorEvent( AnimatorEvent.START, this ) ;
        
        dispatchEvent(_startEvent);
    }
    
    
    private function notifyStop() : void
    {
        
        if( !_isPlaying )
        {
            
            return;
            
        }
        
        _isPlaying = false;
        
        if( _broadcaster.hasEventListener( Event.ENTER_FRAME ) ) 
        {
            
            _broadcaster.removeEventListener( Event.ENTER_FRAME, onEnterFrame ) ;
            
        }
        
        if( !hasEventListener( AnimatorEvent.STOP ) ) return ;
        if( !_stopEvent ) _stopEvent = new AnimatorEvent( AnimatorEvent.STOP, this ) ;
        
        dispatchEvent( _stopEvent ) ;
        
    }
    
    
    /**
     * Updates the animation state.
     * @private
     */
    private function updateAnimation( realDT: Float, scaledDT: Float )
    {
        
        throw new AbstractMethodError() ;
        
    }
    
    
    private function start()
    {
        
        _time = Date.getTimer() ;
        
        if( !_broadcaster.hasEventListener( Event.ENTER_FRAME ) )
        {
            
            _broadcaster.addEventListener( Event.ENTER_FRAME, onEnterFrame ) ;
            
        }
        
        notifyStart();
        
    }
    
    
    private function onEnterFrame( ?event : Event = null )
    {
        
        var time    = Date.getTimer() ;
        var dt      = time-_time ;
        
        updateAnimation( dt, dt*_timeScale );
        
        _time       = time;
        
    }
    
    
}